package com.ly.demo.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.ly.demo.entity.SmResult;
import com.ly.demo.service.impl.SseService;
import com.ly.demo.vo.SecondIpcountVO;
import com.ly.demo.weixin.req.ConversationStreamListener;
import com.ly.demo.weixin.req.SendSseReq;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSources;
import org.apache.poi.ss.usermodel.*;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
@RequestMapping("/demo")
@Slf4j
public class DemoController {

    private ConcurrentHashMap<String, AtomicInteger> ipCount=new ConcurrentHashMap<>();

    private ConcurrentHashMap<String, SecondIpcountVO> secondIpcount=new ConcurrentHashMap<>();


    /**
     * ip计数器
     *
     * @param request
     * @return
     */
    @GetMapping("/ipCount")
    public String ipCount(HttpServletRequest request){
        AtomicInteger atomicInteger = ipCount.computeIfAbsent(request.getRemoteAddr(), key -> new AtomicInteger());
        atomicInteger.incrementAndGet();
        return Convert.toStr(atomicInteger.get());
    }

    /**
     * ip计数器(一秒内)
     *
     * @return
     */
    @GetMapping("/secondIpcount")
    public String secondIpcount(HttpServletRequest request){
        SecondIpcountVO secondIpcountVO = secondIpcount.compute(request.getRemoteAddr(), (key, oldValue) -> {
            if (ObjUtil.isEmpty(oldValue) || System.currentTimeMillis() - oldValue.getTime() > 1000) {
                return new SecondIpcountVO(new AtomicInteger(1), System.currentTimeMillis());
            }
            oldValue.getAtomicInteger().incrementAndGet();
            return oldValue;
        });
        return Convert.toStr(secondIpcountVO.getAtomicInteger().get());
    }

    @Resource
    private SseService sseService;
    /**
     * sse请求
     *
     * @return
     */
    @GetMapping("/sse/{unionKey}")
    public SseEmitter sse(@PathVariable("unionKey")String unionKey){
        return  sseService.createEmitter(unionKey);
    }

    @PostMapping("/sendSse")
    public SmResult sendSse(@RequestBody SendSseReq req){
        sseService.sendEvent(req.getUnionKey(),"test",req.getMessage());
        return SmResult.ok();
    }

    private final static Long CHAT_TIMEOUT = Duration.ofMinutes(1).toMillis();

    /**
     * 打字机效果
     * @return
     */
    @GetMapping(value="/mockChatGpt",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter mockChatGpt(){
        //设置10秒超时时间
        SseEmitter emitter = new SseEmitter(CHAT_TIMEOUT);
        // 设置 SSEEmitter 的事件处理程序
        emitter.onCompletion(() -> log.info(LocalDateTime.now() + ", on completion"));
        emitter.onTimeout(() -> {
            emitter.complete();
        });
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
        // 启动一个新的线程来生成 SSE 事件
        executorService.submit(() -> {
            try {
                String demoStr="本项目旨在开发一款智能家居管理系统，通过整合多种智能设备，实现对家庭环境的全面监控和控制。系统将包括移动应用、Web平台以及云端数据处理功能，提供用户友好的操作界面和智能化的家居体验。";
                List<String> randomStrList = StrUtil.split(demoStr, "，");
                for (String content : randomStrList) {
                    emitter.send(SseEmitter.event().name("message").data(content));
                    Thread.sleep(RandomUtil.randomInt(2000));
                }
            } catch (Exception e) {
                log.error("streamChat:", e);
                emitter.completeWithError(e);
            } finally {
                emitter.complete();
            }
        });
        return emitter;
    }

    /**
     * 打字机效果
     * @return
     */
    @GetMapping("/remotingSse")
    public SseEmitter remotingSse(){
        //设置10秒超时时间
        SseEmitter emitter = new SseEmitter(CHAT_TIMEOUT);
        // 设置 SSEEmitter 的事件处理程序
        emitter.onCompletion(() -> log.info(LocalDateTime.now() + ", on completion"));
        emitter.onTimeout(() -> {
            emitter.complete();
        });
        OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(5, TimeUnit.MINUTES).readTimeout(5, TimeUnit.MINUTES).build();
        Request okhttpRequest = new Request.Builder().url("http://localhost:8083/demo/mockChatGpt").get().build();
        ConversationStreamListener con = new ConversationStreamListener(emitter);
        EventSource.Factory factory = EventSources.createFactory(okHttpClient);
        factory.newEventSource(okhttpRequest, con);
        return emitter;
    }


    /**
     * excel导出
     * @return
     */
    @GetMapping("/export")
    public void export(HttpServletResponse response) throws IOException {
        ClassPathResource classPathResource = new ClassPathResource("scores_tmp.xlsx");
        InputStream in = classPathResource.getInputStream();
        Workbook workbook = WorkbookFactory.create(in);
        Sheet sheet = workbook.getSheetAt(0);
        Row row1 = sheet.createRow(0);
        Cell cell = row1.createCell(0);
        cell.setCellValue("周末考试成绩");
        // 创建一个CellStyle来设置单元格样式
        CellStyle style = workbook.createCellStyle();
        // 设置居中对齐
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // 创建一个Font来设置字体
        Font font = workbook.createFont();
        font.setFontName("宋体");       // 设置字体为宋体
        font.setFontHeightInPoints((short) 16); // 设置字体大小为16号
        font.setBold(true);             // 设置加粗
        font.setColor(IndexedColors.WHITE.getIndex()); // 设置字体颜色为白色
        // 将Font设置到CellStyle
        style.setFont(font);
        // 设置单元格背景颜色
        style.setFillForegroundColor(IndexedColors.BLUE.getIndex()); // 设置背景颜色为蓝色
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 设置填充模式
        // 将CellStyle设置到单元格
        cell.setCellStyle(style);
        // 自动调整列宽以适应内容
        sheet.autoSizeColumn(0);

        Row row2= sheet.createRow(2);
        row2.createCell(0).setCellValue("姓名");
        row2.createCell(1).setCellValue("总分");
        for(int i=2;i<10;i++){
            row2.createCell(i++).setCellValue("第"+i+"题");
        }
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'" + URLEncoder.encode("考试表.xlsx", "UTF-8"));
        workbook.write(response.getOutputStream());
    }
}
